/**
  ******************************************************************************
  * @file    bsp_flash_iap.c
  * @author  Iron
  * @date    2021-02-07
  * @version v1.0
  * @brief   bsp_flash_iap c file
  */

/* Private includes ----------------------------------------------------------*/
#include "bsp_flash_iap.h"
#include "bsp_watchdog.h"

/* BEBUG LOG */
#include "debug_log.h"
#define LOG_LOCAL_LEVEL     DBG_LOG_DEBUG
DBG_LOG_TAG("BSP_FLASH_IAP");

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

/*----------------------------------------------------------------------------*/
int bsp_flash_iap_read(uint32_t addr, uint8_t *data, size_t size)
{
    int i;

    for (i = 0; i < size; i++)
    {
        data[i] = *(uint8_t *)addr;
        addr++;
    }

    return i;
}

/*----------------------------------------------------------------------------*/
int bsp_flash_iap_write(uint32_t addr, const uint8_t *data, size_t size)
{
    uint16_t wdata_16, rdata_16;

    bsp_watchdog_feed();

    HAL_FLASH_Unlock();

    for (int i = 0; i < size; i += 2)
    {
        wdata_16 = data[i] | (data[i + 1] << 8); // little end

        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, wdata_16) != HAL_OK)
        {
            DBG_LOGE(TAG, "flash iap write error.(addr: 0x%08X)", addr);
            break;
        }

        rdata_16 = *(uint16_t *)addr;

        if (wdata_16 != rdata_16)
        {
            DBG_LOGE(TAG, "flash iap write data error.(addr: 0x%08X, write: 0x%02X, read: 0x%02X)", addr, wdata_16, rdata_16);
            break;
        }

        addr +=  2;
    }

    HAL_FLASH_Lock();

    return size;
}

/*----------------------------------------------------------------------------*/
int bsp_flash_iap_erase(uint32_t addr, size_t size)
{
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;

    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.PageAddress = addr;
    EraseInitStruct.NbPages = size / FLASH_PAGE_SIZE;

    bsp_watchdog_feed();

    HAL_FLASH_Unlock();

    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
    {
        DBG_LOGE(TAG, "flash iap erase error.(addr: 0x%08X, PageError: 0x%08X)", addr, PageError);
    }

    HAL_FLASH_Lock();

    return size;
}


/**
  * @}
  */

/******************* (C)COPYRIGHT 2021 ***** END OF FILE *********************/
